﻿Imports Microsoft.Xna.Framework
Imports Microsoft.Xna.Framework.Graphics
Imports Runa.Foundation.Algorithm
Imports Runa.Resources.ContentManagers
Imports Runa.Foundation.Diagnostics

Namespace Global.Runa.Resources.ResourceManager

    Public Enum AnchorPoint As Integer
        LeftUpper
        LeftMiddle
        LeftLower
        RightUpper
        RightMiddle
        RightLower
        Center
    End Enum

    Public Class Texture2DObject
        Inherits ResourceObjectBase

        Public Property Texture() As Graphics.Texture2D

        Public ReadOnly Property Texture(ByVal g As Game) As Graphics.Texture2D
            Get
                If Me.Texture Is Nothing Then
                    Me.Load(g)
                End If
                Return Me.Texture
            End Get
        End Property

        Public ReadOnly Property Size() As Vector2
            Get
                Return Me.Texture.GetSize()
            End Get
        End Property

        Public Sub New()
            MyBase.New()
        End Sub

        Public Sub New(ByVal name As String, ByVal fileName As String)
            MyBase.New(name, fileName)
        End Sub

        Public Sub New(ByVal name As String, ByVal fileName As String, ByVal texture As Graphics.Texture2D)
            MyBase.New(name, fileName)
            Me.Texture = texture
            Me.IsLoaded = True
        End Sub

        Public Sub New(ByVal texture As RenderTarget2D)
            MyBase.New("", "")
            Me.Texture = texture
            Me.IsLoaded = True
        End Sub

        Public Sub New(ByVal name As String, ByVal fileName As String, ByVal game As Game)
            MyBase.New(name, fileName)
            Me.Load(game)
        End Sub

        Public Function GetData(Of T As Structure)() As T()
            Dim srcData(0) As T
            Array.Resize(srcData, Me.Texture.Width * Me.Texture.Height)
            Me.Texture.GetData(Of T)(srcData)
            Return srcData
        End Function

        Public Overrides Function Load(g As Game) As Boolean
            If Me.IsLoaded Then Return True
            Try
                Me.Texture = g.Content.Load(Of Texture2D)(Me.FileName)
            Catch ex As Exception
                Using ms As New MemoryStream(CType(g.Content, BasicContentManager).LoadAllBytes(Me.FileName))
                    Me.Texture = Texture2D.FromStream(g.GraphicsDevice, ms)
                End Using
                'For i As Integer = 0 To 5
                '    Try
                '        Using ms As New MemoryStream(CType(g.Content, BasicContentManager).LoadAllBytes(Me.FileName))
                '            Me.Texture = Texture2D.FromStream(g.GraphicsDevice, ms)
                '        End Using
                '        Exit For
                '    Catch _ex As Exception
                '        If i < 5 Then
                '            Continue For
                '        Else
                '            CObj(g).GameTracer.TraceMessage(_ex.Message & vbCrLf & _ex.StackTrace.ToString())
                '            Me.IsLoaded = False
                '            Return False
                '        End If
                '    End Try
                'Next
            End Try
            Me.IsLoaded = True
            Return True
        End Function

        Public Function Scale(ByVal ratio As Single) As Texture2D
            If Me.Texture IsNot Nothing Then
                Dim currentSize = Me.Size
                Return Me.Texture.Scale(currentSize.X * ratio, currentSize.Y * ratio)
            Else
                Return Nothing
            End If
        End Function

        Public Function Scale(ByVal width As Integer, ByVal height As Integer, Optional ByVal aspectRatio As Boolean = False) As Texture2D
            If Me.Texture IsNot Nothing Then
                Return Me.Texture.Scale(width, height, aspectRatio)
            Else
                Return Nothing
            End If
        End Function

        ''' <summary>
        ''' Get some special reference point.
        ''' </summary>
        ''' <param name="a"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Function GetAnchorPoint(ByVal a As AnchorPoint) As Vector2
            Select Case a
                Case AnchorPoint.Center
                    Return New Vector2(Me.Texture.Width \ 2, Me.Texture.Height \ 2)
                Case AnchorPoint.LeftLower
                    Return New Vector2(0, Me.Texture.Width)
                Case AnchorPoint.LeftMiddle
                    Return New Vector2(0, Me.Texture.Width \ 2)
                Case AnchorPoint.LeftUpper
                    Return New Vector2(0, 0)
                Case AnchorPoint.RightLower
                    Return New Vector2(Me.Texture.Height, Me.Texture.Width)
                Case AnchorPoint.RightMiddle
                    Return New Vector2(Me.Texture.Height, Me.Texture.Width \ 2)
                Case AnchorPoint.RightUpper
                    Return New Vector2(Me.Texture.Height, 0)
            End Select
        End Function

        Public Shared Function GetPureColorTexture(ByVal c As Microsoft.Xna.Framework.Color, ByVal width As Integer, ByVal height As Integer, ByVal g As GraphicsDevice) As Texture2D
            Return c.GetPureColorTexture(width, height, g)
        End Function

        Public Shared Function GetPureColorTextureObject(ByVal c As Microsoft.Xna.Framework.Color, ByVal width As Integer, ByVal height As Integer, ByVal g As GraphicsDevice) As Texture2DObject
            Dim t = c.GetPureColorTexture(width, height, g)
            Return New Texture2DObject("Transparent", "Transparent", t)
        End Function

        Public Shared Function LoadFromData(ByVal g As GraphicsDevice, ByVal data() As Byte, Optional ByVal height As Integer = -1, Optional ByVal width As Integer = -1, Optional ByVal zoom As Boolean = True) As Texture2DObject
            Using ms As New MemoryStream(data)
                Return Texture2DObject.LoadFromStream(g, ms, height, width, zoom)
            End Using
        End Function

        Public Shared Function LoadFromStream(ByVal g As GraphicsDevice, ByVal stream As Stream, Optional ByVal height As Integer = -1, Optional ByVal width As Integer = -1, Optional ByVal zoom As Boolean = True) As Texture2DObject
            Dim texture As Texture2D
            If height <> -1 And width <> -1 Then
                texture = Texture2D.FromStream(g, stream, width, height, zoom)
            Else
                texture = Texture2D.FromStream(g, stream)
            End If
            texture.PreMultiplyAlphas()
            Return New Texture2DObject("", "", texture)
        End Function

        Protected Overrides Sub Dispose(disposing As Boolean)
            If Me.Texture IsNot Nothing AndAlso Me.Texture.IsDisposed = False Then
                Try
                    Me.Texture.Dispose()
                    Me.Texture = Nothing
                Catch ex As Exception
                    Tracer.Default.TraceMessage(ex.Message & vbCrLf & ex.StackTrace.ToString())
                    Exit Try
                End Try
            End If
            MyBase.Dispose(disposing)
        End Sub

        Public Shared Widening Operator CType(ByVal tex As Texture2D) As Texture2DObject
            Return New Texture2DObject("", DateTime.Now.ToString(), tex)
        End Operator

    End Class

End Namespace